package com.fp.m7.dao;

import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.repository.GraphRepository;

import com.fp.m7.api.util.Clock;
import com.fp.m7.model.EntityBase;

public class BaseDaoImpl<T extends EntityBase, G extends GraphRepository<T>>
		implements BaseDao<T> {

	protected G repository;

	private static Validator validator = Validation
			.buildDefaultValidatorFactory().getValidator();

	@Autowired
	protected Clock clock;

	@Override
	public T getById(Long id) {
		return repository.findOne(id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> listAll() {
		EndResult<T> result = repository.findAll();
		return result.as(List.class);
	}

	@Override
	public T persist(T object) {
		prePersist(object);
		validate(object);

		return repository.save(object);
	}

	protected void prePersist(T object) {
		object.setAuditCD(clock.getDateAsLong());
	}

	@Override
	public T merge(T object) {
		validate(object);
		return repository.save(object);
	}

	@Override
	public void remove(T object) {
		repository.delete(object);
	}

	public void setRepository(G repository) {
		this.repository = repository;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected void validate(T object) {
		Set<ConstraintViolation<T>> errors = validator.validate(object);
		if (!errors.isEmpty()) {
			throw new ConstraintViolationException((Set) errors);
		}
	}
}
